package com.ft.oa.service.approval.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ft.oa.domain.approval.ApplyForApproval;
import com.ft.oa.domain.dev.WeeklyReport;
import com.ft.oa.domain.dto.ApiResult;
import com.ft.oa.domain.dto.sys.SecurityUser;
import com.ft.oa.enums.ApprovalParams;
import com.ft.oa.mapper.approval.ApplyForApprovalMapper;
import com.ft.oa.mapper.dev.WeeklyReportMapper;
import com.ft.oa.mapper.sys.SysUserMapper;
import com.ft.oa.security.constant.SecurityConstant;
import com.ft.oa.service.approval.ApplyForApprovalService;
import com.ft.oa.service.project.BidProjectService;
import com.ft.oa.service.project.ExecProjectService;
import com.ft.oa.service.task.TaskMsg;
import com.ft.oa.service.task.TaskService;
import com.ft.oa.utils.SecurityUtils;
import com.ft.oa.utils.SpringContext;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.swing.plaf.nimbus.AbstractRegionPainter;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 审批接口impl
 * @author liyansheng
 * @ClassName ApplyForApprovalMapper
 * @date 2022-1-17 15:50:27
 */
@Service
public class ApplyForApprovalServiceImpl implements ApplyForApprovalService {

    @Resource
    private ApplyForApprovalMapper applyForApprovalMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private WeeklyReportMapper weeklyReportMapper;


    /**
     * 根据根据用户查询代办（待审批）数据、已审批数据、抄送数据
     * @param userId  关联业务表主键 toDoList-待办 doneList-已办 copyList-抄送
     * @return
     */
    @Override
    public ApiResult selectToDoList(Long userId) {
        //封装结果集
        HashMap<String,Object> hashMap = new HashMap<>();
        //待审批
        QueryWrapper<ApplyForApproval> wrapper0 = new QueryWrapper<>();
        wrapper0.lambda().eq(ApplyForApproval::getUserId,userId)
                .eq(ApplyForApproval::getCurrentApprovalStatus,1)//待审批
                .eq(ApplyForApproval::getUserType,0);//审批人
        List<ApplyForApproval> toDoList = applyForApprovalMapper.selectList(wrapper0.orderByDesc("id"));
        //遍历查询业务名称
        toDoList.forEach(e->{
            String relationName = getRelationName(e);//查询申请名称
            e.setRelationName(relationName);
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        hashMap.put("toDoList",toDoList);
        //已审批
        QueryWrapper<ApplyForApproval> wrapper1 = new QueryWrapper<>();
        wrapper1.lambda().eq(ApplyForApproval::getUserId,userId)
                .eq(ApplyForApproval::getCurrentApprovalStatus,2)//已审批
                .eq(ApplyForApproval::getApprovalStatus,0)
                .eq(ApplyForApproval::getUserType,0);//审批人;
        List<ApplyForApproval> doneList = applyForApprovalMapper.selectList(wrapper1.orderByDesc("id"));
        doneList.forEach(e -> {
            String relationName = getRelationName(e);//查询申请名称
            e.setRelationName(relationName);
            e.setApprovalResultName((e.getApprovalResult() == 1) ? "同意" : "驳回");
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        hashMap.put("doneList",doneList);
        //抄送：如果申请已经通过或者驳回则在抄送列表里面不显示
        QueryWrapper<ApplyForApproval> wrapper2 = new QueryWrapper<>();
        wrapper2.lambda().eq(ApplyForApproval::getUserId,userId)
                .eq(ApplyForApproval::getUserType,1)
                .eq(ApplyForApproval::getApprovalStatus,0);//抄送人;
        List<ApplyForApproval> copyList = applyForApprovalMapper.selectList(wrapper2.orderByDesc("id"));
        copyList.forEach(e->{
            String relationName = getRelationName(e);//查询申请名称
            e.setRelationName(relationName);
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        hashMap.put("copyList",copyList);
        //我创建的
        QueryWrapper<ApplyForApproval> wrapper3 = new QueryWrapper<>();
        wrapper3.lambda().eq(ApplyForApproval::getCreator,userId);
        List<ApplyForApproval> createdList = applyForApprovalMapper.selectList(wrapper3.orderByDesc("id"));
        List<ApplyForApproval> createdListResult = createdList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() ->
                                new TreeSet<>(Comparator.comparing(o -> o.getRelationId() + ";" + o.getRelationType()))), ArrayList::new));
        createdListResult.forEach(e -> {
            String relationName = getRelationName(e);//查询申请名称
            e.setRelationName(relationName);
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        hashMap.put("createdList",createdListResult);
        //已完成的
        QueryWrapper<ApplyForApproval> wrapper4 = new QueryWrapper<>();
        wrapper4.lambda().eq(ApplyForApproval::getUserId,userId)
                .or().eq(ApplyForApproval::getCreator,userId)
                .ne(ApplyForApproval::getApprovalStatus,0);  //主表状态已经完成的
        List<ApplyForApproval> finishList = applyForApprovalMapper.selectList(wrapper4.orderByDesc("id"));
        List<ApplyForApproval> finishListResult = finishList.stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() ->
                                new TreeSet<>(Comparator.comparing(o -> o.getRelationId() + ";" + o.getRelationType()))), ArrayList::new));
        finishListResult.forEach(e -> {
            String relationName = getRelationName(e);//查询申请名称
            e.setRelationName(relationName);
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
            if (e.getUserType() == 0 ) {  //审批
                 e.setApprovalResultName(e.getApprovalStatus() == 1 ? "通过" : "驳回");
            }
        });
        hashMap.put("finishList",finishListResult);
        SecurityUser currentUser = SecurityUtils.getCurrentUser();
        //获取用户权限 如果是admin 则是管理员 可以查看到全部
        Set<String> roles = currentUser.getRoles();
        QueryWrapper<WeeklyReport> wrapper5 = new QueryWrapper<>();
        wrapper5.eq("report_type",0);
        boolean roledesc = false;
        for (String role:roles) {
            if(role.equals(SecurityConstant.SUPER_ROLE)){
                roledesc = true;
                break;
            }
        }
        if(!roledesc){
            wrapper5.eq("create_staff_id",userId);
        }
        Integer reportCount = weeklyReportMapper.selectCount(wrapper5);
        hashMap.put("reportCount",reportCount);
        return ApiResult.successWithData(hashMap);
    }

    /**
     * 根据业务主键查询所有 ApprovalUsers-审批人，CopyUsers-抄送人
     * @param relationId  关联业务表主键
     * @param relationType 关联审批分类 1、合同审批 2、协同审批 3、投标审批  4、立项审批  5、验收审批
     *       6、成本变更审批  7、进度变更审批  8、研发立项审批  9、采购审批
     * @return
     */
    @Override
    public ApiResult selectAllUser(Long relationId,Integer relationType){
        HashMap<String,Object> hashMap = new HashMap<>();
        QueryWrapper<ApplyForApproval> wrapper0 = new QueryWrapper<>();
        wrapper0.lambda().eq(ApplyForApproval::getRelationId,relationId)
                .eq(ApplyForApproval::getRelationType,relationType)
                .eq(ApplyForApproval::getUserType,0);//审批人
        List<ApplyForApproval> approvalUsers = applyForApprovalMapper.selectList(wrapper0);
        approvalUsers.forEach(e->{
            e.setUserName(sysUserMapper.selectById(e.getUserId()).getNickname());
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        hashMap.put("approvalUsers",approvalUsers);
        QueryWrapper<ApplyForApproval> wrapper1 = new QueryWrapper<>();
        wrapper1.lambda().eq(ApplyForApproval::getRelationId,relationId)
                .eq(ApplyForApproval::getRelationType,relationType)
                .eq(ApplyForApproval::getUserType,1);//抄送人
        List<ApplyForApproval> copyUsers = applyForApprovalMapper.selectList(wrapper1);
        copyUsers.forEach(e->{
            e.setUserName(sysUserMapper.selectById(e.getUserId()).getNickname());
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        hashMap.put("copyUsers",copyUsers);
        return ApiResult.successWithData(hashMap);
    }

    /**
     * 根据业务表主键审批人
     * @param relationId  关联业务表主键
     * @return
     */
    @Override
    public List<ApplyForApproval> selectApprovalUser(Long relationId,Integer relationType){
        QueryWrapper<ApplyForApproval> wrapperApprovalUser = new QueryWrapper<>();
        wrapperApprovalUser.lambda().eq(ApplyForApproval::getRelationId,relationId)
                .eq(ApplyForApproval::getRelationType,relationType)
                .eq(ApplyForApproval::getUserType,0);//审批人
        List<ApplyForApproval> approvalUsers = applyForApprovalMapper.selectList(wrapperApprovalUser);
        approvalUsers.forEach(e->{
            e.setUserName(sysUserMapper.selectById(e.getUserId()).getNickname());
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
            if(e.getCurrentApprovalStatus()==2){
                e.setApprovalResultName((e.getApprovalResult()==1)?"同意":"驳回");
            }else{
                e.setApprovalResultName((e.getCurrentApprovalStatus()==1)?"待审批":"待流转");
            }
        });
        return approvalUsers;
    }

    /**
     * 根据抄送人
     * @param relationId  关联业务表主键
     * @return
     */
    @Override
    public List<ApplyForApproval> selectCopyUser(Long relationId,Integer relationType){
        QueryWrapper<ApplyForApproval> wrapper0 = new QueryWrapper<>();
        wrapper0.lambda().eq(ApplyForApproval::getRelationId,relationId)
                .eq(ApplyForApproval::getRelationType,relationType)
                .eq(ApplyForApproval::getUserType,1);//抄送人
        List<ApplyForApproval> copyUsers = applyForApprovalMapper.selectList(wrapper0);
        copyUsers.forEach(e->{
            e.setUserName(sysUserMapper.selectById(e.getUserId()).getNickname());
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
        });
        return copyUsers;
    }

    /**
     * 对接前请维护枚举ApprovalParams:
     * 添加审批人 至少传递3个字段 userId(审批人id:必填)、relationId(关联业务主键:必填)、relationType(关联审批类型:必填)、relationCode(关联业务编码:非必须)
     * @author liyansheng
     * @param applyForApproval
     * @return
     */
    @Override
    @Transactional
    public ApiResult addApproval(List<ApplyForApproval> applyForApproval) {
        if(applyForApproval==null){
            return ApiResult.builder().code(200).msg("审批人为空").build();
        }
        applyForApproval.forEach(e->{
            e.setUserType(0);
            //编辑当前人眼的审批状态。如果是第一个节点人员则当前审批节点状态为【待审批】否则为【未流转】。当审批过后状态修改为【已审批】
            //当前审批人节点状态 0-未流转 1-待审批 2-已审批(当前审批人审批过后更新下一审批人状态)
            //判断是否为第一个节点
            int index = applyForApproval.indexOf(e);
            e.setCurrentApprovalStatus(index==0?1:0);
            //判断是否是最终审批人(用以更改业务表审核状态：如果最终用户审批通过则业务表审核通过)
            e.setLastUser((index==(applyForApproval.size()-1))?1:0);
            e.setSeq(index);
            e.setApprovalStatus(0);
            applyForApprovalMapper.insert(e);
        });
        return ApiResult.simpleSuccess();
    }

    /**
     * 添加抄送人 至少传递3个字段 userId(审批人id:必填)、relationId(关联业务主键:必填)、relationType(关联审批类型:必填)、relationCode(关联业务编码:非必须)
     * @author liyansheng
     * @param applyForApproval
     * @return
     */
    @Override
    @Transactional
    public ApiResult addCarbonCopy(List<ApplyForApproval> applyForApproval) {
        if(applyForApproval==null){
            return ApiResult.builder().code(200).msg("抄送人为空").build();
        }
        applyForApproval.forEach(e->{
            e.setUserType(1);
            e.setApprovalStatus(0);
            applyForApprovalMapper.insert(e);
        });
        return ApiResult.simpleSuccess();
    }

    /**
     * 审批通过
     * @param applyForApproval
     * @return
     */
    @Override
    @Transactional
    public ApiResult approve(ApplyForApproval applyForApproval) {
        //查询数据库获取当前节点详细信息
        ApplyForApproval dbApplay = applyForApprovalMapper.selectById(applyForApproval.getId());
        //更新当前审批人节点数据、包括审批状态、审批意见、审批时间等
        dbApplay.setCurrentApprovalStatus(2);
        //先注释掉，当最后一个审批人审批后统一更新这批记录
        //dbApplay.setApprovalStatus(1);
        dbApplay.setApprovalResult(1);
        dbApplay.setApprovalTime(LocalDateTime.now());
        dbApplay.setApprovalOpinion(applyForApproval.getApprovalOpinion());
        applyForApprovalMapper.updateById(dbApplay);
        //判断当前审批人是否是最终审批人，如果是则更新业务表状态为审核通过
        if(dbApplay.getLastUser()==1){
            dbApplay.setApprovalStatus(1);//审批通过
            updateApprovalStatus(dbApplay);
        }else{
            //如果不是是更新下一审批人节点状态为待审批
            dbApplay.setSeq(dbApplay.getSeq()+1);
            updateNextUser(dbApplay);
        }
        return ApiResult.simpleSuccess();
    }

    /**
     * 驳回：只要有一个驳回则业务就设置成驳回状态
     * @param applyForApproval
     * @return
     */
    @Override
    @Transactional
    public ApiResult reject(ApplyForApproval applyForApproval) {
        //查询数据库获取当前节点详细信息
        ApplyForApproval dbApplay = applyForApprovalMapper.selectById(applyForApproval.getId());
        //更新审批表数据
        dbApplay.setCurrentApprovalStatus(2);
        dbApplay.setApprovalResult(0);
        dbApplay.setApprovalStatus(2);
        dbApplay.setApprovalTime(LocalDateTime.now());
        dbApplay.setApprovalOpinion(applyForApproval.getApprovalOpinion());
        applyForApprovalMapper.updateById(dbApplay);
        //更新业务表状态
        dbApplay.setApprovalStatus(2);//审核驳回
        updateApprovalStatus(dbApplay);
        return ApiResult.simpleSuccess();
    }

    /**
     * 抄送人提意见 一个抄送人对同一申请可以提多条意见（目前设计是在每个意见基础上加上<br />换行符,需要前端去解析标签）
     * id（抄送表主键） 和 approvalOpinion（审批意见） 为必录项
     * @param applyForApproval
     * @return
     */
    @Override
    @Transactional
    public ApiResult exchangeViews(ApplyForApproval applyForApproval) {
        //查询数据库获取当前节点详细信息
        ApplyForApproval dbApplay = applyForApprovalMapper.selectById(applyForApproval.getId());
        if(StringUtils.isNotEmpty(dbApplay.getApprovalOpinion())){
            dbApplay.setApprovalOpinion(dbApplay.getApprovalOpinion()+"<br/>"+applyForApproval.getApprovalOpinion());
        }else{
            dbApplay.setApprovalOpinion(applyForApproval.getApprovalOpinion());
        }
        dbApplay.setApprovalTime(LocalDateTime.now());
        applyForApprovalMapper.updateById(dbApplay);
        return ApiResult.simpleSuccess();
    }


    /**
     * 更新业务表审批状态，同时更新审批人抄送人表业务字段审批状态
     * @return
     */
    @Override
    public void updateApprovalStatus(ApplyForApproval applyForApproval) {
        //更新业务表数据
        ApprovalParams byCode = ApprovalParams.getByCode(applyForApproval.getRelationType());
        String table = byCode.getTable();
        String approvalColumn = byCode.getApprovalColumn();
        int approvalStatus = applyForApproval.getApprovalStatus();
        Long relationId = applyForApproval.getRelationId();
        applyForApprovalMapper.updateApprovalStatus(table,approvalColumn,approvalStatus,relationId);
        //更新审批人抄送人表最终业务字段审核状态(该字用于查询【抄送我的】进行过滤)
        UpdateWrapper<ApplyForApproval> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("relation_id",applyForApproval.getRelationId());
        updateWrapper.eq("relation_type",applyForApproval.getRelationType()); //根据RelationId以及RelationType锁定唯一数据
        updateWrapper.set("approval_status",approvalStatus);
        applyForApprovalMapper.update(null, updateWrapper);
        //执行回调
        if(applyForApproval.getCallBack() && (applyForApproval.getCallBackMsg() != null)){

            String callBackMsg = applyForApproval.getCallBackMsg();
            TaskMsg taskMsg = JSONObject.parseObject(callBackMsg, TaskMsg.class);
            if(applyForApproval.getApprovalStatus().equals(taskMsg.getType())){
                TaskService aTask = SpringContext.getBean(taskMsg.getName());
                aTask.exec(taskMsg.getParams());
            }

        }
    }

    /**
     * 更新下一审批人状态为待审批
     * @param applyForApproval
     */
    public void updateNextUser(ApplyForApproval applyForApproval){
        UpdateWrapper<ApplyForApproval> updateWrapper = new UpdateWrapper();
        //根据三个字段确定下一节点数据
        updateWrapper.eq("relation_id",applyForApproval.getRelationId());
        updateWrapper.eq("relation_type",applyForApproval.getRelationType());
        updateWrapper.eq("seq",applyForApproval.getSeq());
        updateWrapper.set("current_approval_status",1);
        applyForApprovalMapper.update(null, updateWrapper);
    }

    /**
     * 获取业务表业务名称
     * @param applyForApproval
     * @return
     */
    public String getRelationName(ApplyForApproval applyForApproval) {
        ApprovalParams byCode = ApprovalParams.getByCode(applyForApproval.getRelationType());
        String table = byCode.getTable();
        String businessNameColumn = byCode.getBusinessNameColumn();
        Long relationId = applyForApproval.getRelationId();
        String relationName = applyForApprovalMapper.getRelationName(table,businessNameColumn,relationId);
        return relationName;
    }

    /**
     * 根据关联id删除审批人\抄送人
     * @param relationId
     * @return
     */
    @Override
    public int delApprovalCopyUser(Long relationId) {
        QueryWrapper<ApplyForApproval> execProjectCheckQueryWrapper = new QueryWrapper<>();
        execProjectCheckQueryWrapper.lambda().eq(ApplyForApproval::getRelationId, relationId);
        return applyForApprovalMapper.delete(execProjectCheckQueryWrapper);
    }

    /**
     * 已读
     * @param id
     * @return
     */
    @Override
    public ApiResult read(Integer id) {
        UpdateWrapper<ApplyForApproval> updateWrapper = new UpdateWrapper();
        //根据主键修改为已读
        updateWrapper.eq("id",id);
        updateWrapper.set("read_status",1);
        applyForApprovalMapper.update(null, updateWrapper);
        return ApiResult.simpleSuccess();
    }

    @Override
    public List<ApplyForApproval> selectBusinessProcessNodeList(Long relationId, Integer relationType) {
        QueryWrapper<ApplyForApproval> wrapper0 = new QueryWrapper<>();
        wrapper0.eq("relation_id", relationId);
        wrapper0.eq("relation_type", relationType);
        wrapper0.orderByAsc("(CASE WHEN `approval_time` IS NULL THEN 1 ELSE 0 END)");
        wrapper0.orderByAsc("`approval_time`");
        List<ApplyForApproval> businessProcessNodeList = applyForApprovalMapper.selectList(wrapper0);
        businessProcessNodeList.forEach(e -> {
            e.setUserName(sysUserMapper.selectById(e.getUserId()).getNickname());
            e.setCreatorName(sysUserMapper.selectById(e.getCreator()).getNickname());
            if (e.getUserType() == 0 && e.getCurrentApprovalStatus() == 2) {  //审批
                e.setApprovalResultName((e.getApprovalResult() == 1) ? "同意" : "驳回");
            }
            if(e.getUserType() == 0 && e.getCurrentApprovalStatus() != 2) { //审批
                e.setApprovalResultName((e.getCurrentApprovalStatus() == 1) ? "待审批" : "待流转");
            }
            if(e.getUserType() == 1){
                e.setApprovalResultName(e.getRead_status() == 0 ? "未读" : "已读");
            }
        });
        if(!CollectionUtils.isEmpty(businessProcessNodeList)){
            ApplyForApproval applyForApproval = businessProcessNodeList.get(0);
            ApplyForApproval head = new ApplyForApproval();
            BeanUtils.copyProperties(applyForApproval,head);
            head.setUserId(head.getCreator());
            head.setUserName(head.getCreatorName());
            head.setApprovalResultName("发起申请");
            head.setApprovalOpinion(null);
            head.setApprovalTime(head.getCreateTime());
            businessProcessNodeList.add(0,head);
        }
        return businessProcessNodeList;
    }

}
